﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SHKF.B2C.BaseHosted.Model;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO; 
using System.Reflection; 

namespace SHKF.B2C.BaseHosted
{
    public static class HostedExtensions
    {
        /// <summary>
        /// 加载josn文件夹下的所有文件
        /// </summary>
        /// <param name="hostBuilder"></param>
        /// <param name="hostJson"></param>
        /// <returns></returns>
        public static IHostBuilder UseRunJson(this IHostBuilder hostBuilder, string hostJson)
        {
            if (!string.IsNullOrEmpty(hostJson))
            {
                string json2 = "";
                foreach (string fileName in hostJson.Split(","))
                {
                    if (json2 != "")
                    {
                        json2 += ",";
                    }
                    json2 += "json/" + fileName;
                }
                if (!string.IsNullOrEmpty(json2))
                {
                    hostBuilder.UseRunCore(json2);
                }
            }
            else
            {
                string path = AppDomain.CurrentDomain.BaseDirectory + "json";
                if (Directory.Exists(path))
                {
                    string json2 = "";
                    foreach (string fileName in Directory.GetFiles(path))
                    {
                        if (json2 != "")
                        {
                            json2 += ",";
                        }

                        int end1 = fileName.LastIndexOf("\\");
                        string fileName2 = fileName.Substring(end1 + 1, fileName.Length - end1 - 1);
                        json2 += "json/" + fileName2;
                    }

                    if (!string.IsNullOrEmpty(json2))
                    {
                        hostBuilder.UseRunCore(json2);
                    }

                }
            }

            return hostBuilder;
        }


        public static IHostBuilder UseRunCore(this IHostBuilder hostBuilder, string hostJson)
        {

            hostBuilder.ConfigureHostConfiguration(configBuilder => {

                configBuilder.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
                configBuilder.AddJsonFile("appsettings.json", true);

                if (string.IsNullOrEmpty(hostJson)  || !hostJson.Contains("dbList"))
                {
                    configBuilder.AddJsonFile("dbList.json", true);
                }
                
                if (!string.IsNullOrEmpty(hostJson))
                {
                    foreach (string jsonPath in hostJson.Split(','))
                    {
                        string path = jsonPath;
                        if (!path.EndsWith(".json"))
                        {
                            path += ".json";
                        }
                      
                        configBuilder.AddJsonFile(path, true);
                    }
                }
            })
                .ConfigureLogging((context, loggingBuilder) =>
                {
                    loggingBuilder.ClearProviders();
                    loggingBuilder.AddLog4Net(new Log4NetProviderOptions()
                    {
                        Log4NetConfigFileName = "Configs\\log4net.config",
                        Watch = true
                    });
                })
                .ConfigureServices((context, services) =>
                {
                    try
                    {
                        services.AddAllBLL();
                        services.AddOptions();
                        services.AddDB(context); 
                        services.AddControllers(options => options.ModelMetadataDetailsProviders.Add(new CustomMetadataProvider()))
                        .AddJsonOptions(option => {

                            //默认为json按驼峰式输出
                            //options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;

                            //json按大小写原样输出
                            option.JsonSerializerOptions.PropertyNamingPolicy = null; 

                        });

                        services.AddCors(options =>
                        {
                            options.AddPolicy("cors", policy =>
                            {
                                policy.AllowAnyOrigin()
                                    .AllowAnyHeader()
                                    .AllowAnyMethod();
                            });
                        });
                    }
                    catch (System.Exception ex)
                    {
                        System.IO.File.AppendAllText("c://run.log", $"fun:UseRun>> {DateTime.Now} {ex.Message}\t\r");
                    }
                })
                // .UseServiceProviderFactory(new AutofacServiceProviderFactory())//autofac-2
                .UseWindowsService();

            return hostBuilder;
        }

        private static IServiceCollection AddDB(this IServiceCollection services, HostBuilderContext context)
        {

            services.Configure<List<DbEnum>>(context.Configuration.GetSection("DBList"));
            IOptions<List<DbEnum>> dbList = services.BuildServiceProvider().GetService<IOptions<List<DbEnum>>>();

            WriteRunLog("//------------------------------添加DBList:");
            if (dbList != null)
            {
                string ip = context.Configuration.GetSection("ip").Value;

                if (!string.IsNullOrEmpty(ip))
                { 
                    List<ConnectionConfig> iocList = new List<ConnectionConfig>();

                    foreach (DbEnum dbEnum in dbList.Value)
                    {
                        string dbConn = $"{ip}" + dbEnum.dbConn;

                        ConnectionConfig connectionConfig = new ConnectionConfig();
                        connectionConfig.ConfigId = dbEnum.dbName;
                        connectionConfig.ConnectionString = dbConn;
                        connectionConfig.DbType = DbType.SqlServer;
                        connectionConfig.IsAutoCloseConnection = true;
                        iocList.Add(connectionConfig);

                        WriteRunLog($"dbName:{dbEnum.dbName} dbConn:{dbEnum.dbConn}");
                    }

                    services.AddTransient<SqlSugarClient>((server) =>
                    {
                        return new SqlSugarClient(iocList);
                    });
                }
            }

            return services;
        }

        private static void WriteRunLog(string context)
        {
            string root = AppDomain.CurrentDomain.BaseDirectory;
            string runPath = root + "run";

            if (!System.IO.Directory.Exists(runPath))
            {
                Directory.CreateDirectory(runPath);
            }
            string path = $"{runPath}\\{DateTime.Now.ToString("yyyy-MM-dd")}.log";
            System.IO.File.AppendAllText(path, $"{DateTime.Now} {context}\r\n");

        }
        private static IServiceCollection AddAllBLL(this IServiceCollection services)
        {
            string root = AppDomain.CurrentDomain.BaseDirectory;
            string[] files = Directory.GetFiles(root);

            WriteRunLog("//------------------------------添加Bll:");
            foreach (string fileName in files)
            {
                FileInfo fileInfo = new FileInfo(fileName);

                if (fileInfo.Name.EndsWith("BLL.dll"))
                {
                    string assemblyString = fileInfo.Name.Replace(fileInfo.Extension, "");
                    Assembly assemblys = Assembly.Load(assemblyString);
                    foreach (Type type in assemblys.GetTypes())
                    {
                        if (type.IsPublic)
                        {
                            WriteRunLog("AddTransient:" + type.FullName);
                            services.AddTransient(type);
                        }
                    }
                }
            }
            return services;
        }
    }
}
